package com.world.rickcloudendpoint.logic.service.impl;

import cn.hutool.core.lang.Assert;
import com.mongodb.client.result.DeleteResult;
import com.world.rickcloudendpoint.common.constant.GlobalConstants;
import com.world.rickcloudendpoint.common.exception.ModuleException;
import com.world.rickcloudendpoint.common.utils.InjectToolUtils;
import com.world.rickcloudendpoint.logic.service.IASignalService;
import com.world.rickcloudendpoint.models.mongo.ASignalDoc;
import com.world.rickcloudendpoint.models.params.QueryParams;
import com.world.rickcloudendpoint.models.result.PageResult;
import com.world.rickcloudendpoint.models.vo.ASignalVO;
import com.world.rickcloudendpoint.service.tools.AggregateQueryTools;
import com.world.rickcloudendpoint.service.tools.MongoDslDecoderTools;
import org.apache.commons.lang3.StringUtils;
import org.bson.types.ObjectId;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @description:
 * @author: jlsong
 * @date: 2022/01/22 22:18:08
 * @version: 1.0
 */
@Service
public class ASignalServiceImpl implements IASignalService {

    final MongoTemplate mongoTemplate;

    public ASignalServiceImpl(MongoTemplate mongoTemplate) {
        this.mongoTemplate = mongoTemplate;
    }

    @Override
    public ASignalVO add(ASignalVO record) throws ModuleException {
        Assert.notNull(record, "新增的实体不能为空");
        // 转换
        ASignalDoc doc = record.toDoc();
        ASignalDoc okDoc = mongoTemplate.insert(doc);
        return okDoc.toVo();
    }

    @Override
    public ASignalVO edit(ASignalVO record) throws ModuleException {
        Assert.notNull(record, "修改的实体不能为空");
        Assert.notBlank(record.getId(), "修改的实体ID不能为空");
        // 转换
        ASignalDoc doc = record.toDoc();
        ASignalDoc okDoc = mongoTemplate.save(doc);
        return okDoc.toVo();
    }

    @Transactional(
            rollbackFor = {Exception.class}
    )
    @Override
    public Long del(String... ids) throws ModuleException {
        Assert.noNullElements(ids, "删除的ID数组不能为空");
        List<String> idList = Arrays.asList(ids);
        List<ObjectId> oidList = idList.stream().map(id -> new ObjectId(id)).collect(Collectors.toList());
        Query query = new Query();
        query.addCriteria(Criteria.where("_id").in(oidList));
        Long total = mongoTemplate.count(query, ASignalDoc.class);
        DeleteResult result = mongoTemplate.remove(query, ASignalDoc.class);
        if (result.wasAcknowledged()) {
            if (result.getDeletedCount() == total) {
                return total;
            }
        }
        return -1L;
    }

    @Override
    public PageResult<ASignalVO> list(String collectionName, QueryParams payload) throws ModuleException {
        Class collectionClass = ASignalDoc.class;
        if (!StringUtils.isEmpty(collectionName)) {
            collectionClass = InjectToolUtils.getClassByPackAndCollectionName(GlobalConstants.Mongodb.DOC_CLASS_PACKAGE_NAME,
                    collectionName);
        }

        Assert.notNull(collectionClass, "数据集名称对应的映射类不存在");
        if (payload == null || payload.getWhere() == null || StringUtils.isBlank(payload.getWhere().getExp())) {
            // 查询全部量
            Query query = new Query();
            if (payload != null) {
                // 设置排序
                Sort sort = AggregateQueryTools.getSorts(payload.getSorts());
                if (sort != null) {
                    query.with(sort);
                }
            }
            long count = mongoTemplate.count(query, collectionClass);
            List<ASignalDoc> list = mongoTemplate.find(query, collectionClass);
            List<ASignalVO> data = list.stream().map(doc -> doc.toVo()).collect(Collectors.toList());
            PageResult<ASignalVO> result = new PageResult<>(1, -1);
            result.setTotal(count);
            result.list(data);
            return result;
        }
        Query query = MongoDslDecoderTools.getMongoQuery(payload.getWhere().getExp(), payload.getWhere().getDict());
        Assert.notNull(query, "查询过滤条件拼接错误");

        // 设置排序
        Sort sort = AggregateQueryTools.getSorts(payload.getSorts());
        if (sort != null) {
            query.with(sort);
        }

        // 设置分页
        if (payload.getPage() != null) {
            Integer num = payload.getPage().getPageNum();
            Integer size = payload.getPage().getPageSize();
            if (num != null && size != null) {
                if (size > 0) {
                    query.skip(AggregateQueryTools.getSkip(payload.getPage()));
                    query.limit(size);
                }
            }
        }

        long count = mongoTemplate.count(query, collectionClass);
        List<ASignalDoc> list = mongoTemplate.find(query, collectionClass);
        List<ASignalVO> data = list.stream().map(doc -> doc.toVo()).collect(Collectors.toList());
        if (payload.getPage().getPageSize() == -1) {
            payload.getPage().setPageNum(1);
        }
        PageResult<ASignalVO> result = new PageResult<>(payload.getPage().getPageNum(), payload.getPage().getPageSize());
        result.setTotal(count);
        result.list(data);
        return result;
    }

    @Transactional(
            rollbackFor = {Exception.class}
    )
    @Override
    public boolean addBatch(List<ASignalVO> list, int batchSize) {
        Assert.noNullElements(list.toArray(), "参数集合不能为空");

        List<ASignalDoc> insertList = list.stream().map(vo -> vo.toDoc()).collect(Collectors.toList());

        Collection<ASignalDoc> okList = mongoTemplate.insert(insertList, ASignalDoc.class);
        return okList.size() == batchSize;
    }
}
